package genedit.aStar;

import java.awt.geom.Point2D;
import java.util.ArrayList;

/**
 * Klasa predstavlja ćelija kroz koju se prolazi za vreme pretrage.
 * 
 * @author Igić
 * @version 1.0 9/12/13
 */
public class Node implements Comparable<Node> {

	/**
	 * Čvor koji se nalazi iznad trenutnog.
	 */
	Node north;
	/**
	 * Čvor koji se nalazi levo od trenutnog.
	 */
	Node east;
	/**
	 * Čvor koji se nalazi ispod trenutnog.
	 */
	Node south;
	/**
	 * Čvor koji se nalazi desno od trenutnog.
	 */
	Node west;
	/**
	 * Lista susednih čvorova.
	 */
	ArrayList<Node> neighborList;
	/**
	 * Proverava da li je čvor obrađivan.
	 */
	boolean visited;
	/**
	 * Udaljenost čvora od starta.
	 */
	double distanceFromStart;
	/**
	 * Procenjena minimalna udaljenost čvora do cilja.
	 */
	double heuristicDistanceFromGoal;
	/**
	 * Prethodno obrađeni čvor.
	 */
	Node previousNode;
	/**
	 * Pozicija čvora.
	 */
	Point2D position;
	/**
	 * Proverava da li se čvor nalazi u grafičkom elementu koji treba zaobići.
	 */
	boolean isObstacle;
	/**
	 * Proverava da li je čvor startni čvor.
	 */
	boolean isStart;
	/**
	 * Proverava da li je čvor ciljni čvor.
	 */
	boolean isGoal;

	Node(Point2D position) {
		neighborList = new ArrayList<Node>();
		this.position = position;
		this.visited = false;
		this.distanceFromStart = Integer.MAX_VALUE;
		this.isObstacle = false;
		this.isStart = false;
		this.isGoal = false;
	}

	Node(Point2D position, boolean visited, int distanceFromStart, boolean isObstical,
			boolean isStart, boolean isGoal) {
		neighborList = new ArrayList<Node>();
		this.position = position;
		this.visited = visited;
		this.distanceFromStart = distanceFromStart;
		this.isObstacle = isObstical;
		this.isStart = isStart;
		this.isGoal = isGoal;
	}

	public Node getNorth() {
		return north;
	}

	public void setNorth(Node north) {
		if (neighborList.contains(this.north))
			neighborList.remove(this.north);
		neighborList.add(north);

		this.north = north;
	}

	public Node getEast() {
		return east;
	}

	public void setEast(Node east) {
		if (neighborList.contains(this.east))
			neighborList.remove(this.east);
		neighborList.add(east);

		this.east = east;
	}

	public Node getSouth() {
		return south;
	}

	public void setSouth(Node south) {
		if (neighborList.contains(this.south))
			neighborList.remove(this.south);
		neighborList.add(south);

		this.south = south;
	}

	public Node getWest() {
		return west;
	}

	public void setWest(Node west) {
		if (neighborList.contains(this.west))
			neighborList.remove(this.west);
		neighborList.add(west);

		this.west = west;
	}

	public ArrayList<Node> getNeighborList() {
		return neighborList;
	}

	public boolean isVisited() {
		return visited;
	}

	public void setVisited(boolean visited) {
		this.visited = visited;
	}

	public double getDistanceFromStart() {
		return distanceFromStart;
	}

	public void setDistanceFromStart(double f) {
		this.distanceFromStart = f;
	}

	public Node getPreviousNode() {
		return previousNode;
	}

	public void setPreviousNode(Node previousNode) {
		this.previousNode = previousNode;
	}

	public double getHeuristicDistanceFromGoal() {
		return heuristicDistanceFromGoal;
	}

	public void setHeuristicDistanceFromGoal(double heuristicDistanceFromGoal) {
		this.heuristicDistanceFromGoal = heuristicDistanceFromGoal;
	}

	public Point2D getPosition() {
		return position;
	}

	public void setPosition(Point2D position) {
		this.position = position;
	}

	public boolean isObstacle() {
		return isObstacle;

	}

	public void setObstacle(boolean isObstacle) {
		this.isObstacle = isObstacle;
	}

	public boolean isStart() {
		return isStart;
	}

	public void setStart(boolean isStart) {
		this.isStart = isStart;
	}

	public boolean isGoal() {
		return isGoal;
	}

	public void setGoal(boolean isGoal) {
		this.isGoal = isGoal;
	}

	public boolean equals(Node node) {
		return (node.position.getX() == this.position.getX())
				&& (node.position.getY() == this.position.getY());
	}

	public int compareTo(Node otherNode) {
		double thisTotalDistanceFromGoal = heuristicDistanceFromGoal + distanceFromStart;
		double otherTotalDistanceFromGoal = otherNode.getHeuristicDistanceFromGoal()
				+ otherNode.getDistanceFromStart();

		if (thisTotalDistanceFromGoal < otherTotalDistanceFromGoal) {
			return -1;
		} else if (thisTotalDistanceFromGoal > otherTotalDistanceFromGoal) {
			return 1;
		} else {
			return 0;
		}
	}
}
